package es.udc.empresauriostic.geofinder.view;

import java.io.IOException;
import java.util.LinkedList;
import java.util.List;

import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.util.Pair;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.SpinnerAdapter;
import android.widget.TextView;

import com.actionbarsherlock.app.ActionBar.OnNavigationListener;
import com.actionbarsherlock.app.SherlockMapActivity;
import com.actionbarsherlock.view.Menu;
import com.actionbarsherlock.view.MenuInflater;
import com.actionbarsherlock.view.MenuItem;
import com.google.android.maps.GeoPoint;
import com.google.android.maps.ItemizedOverlay;
import com.google.android.maps.MapController;
import com.google.android.maps.MapView;
import com.google.android.maps.OverlayItem;

import es.udc.empresauriostic.geofinder.R;
import es.udc.empresauriostic.geofinder.model.GameGlobalStatus;
import es.udc.empresauriostic.geofinder.model.GameUserData;
import es.udc.empresauriostic.geofinder.model.ServerAPI;
import es.udc.empresauriostic.geofinder.model.ServerAPI.SubmittedLocationResponse;
import es.udc.empresauriostic.geofinder.model.utils.Util;
import es.udc.empresauriostic.geofinder.view.utils.ViewUtils;

public class GameActivity extends SherlockMapActivity implements
		LocationListener {
	private GameGlobalStatus gameStatus;
	private List<String> clues;
	private SharedPreferences preferences;
	private CustomItemizedOverlay foundMarkers;
	private CustomItemizedOverlay closeMarkers;
	private CustomItemizedOverlay mediumMarkers;
	private CustomItemizedOverlay farMarkers;
	private CustomItemizedOverlay winMarkers;
	private LocationManager locationManager;
	private MapView mapView;
	private Context context;
	private Dialog currentDialog;

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.game_map_layout);
		this.context = this;
		locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
		locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,
				1000L, 50.0f, this);
		foundMarkers = new CustomItemizedOverlay(getApplicationContext(),
				getResources().getDrawable(R.drawable.green_marker),
				new LinkedList<GeoPoint>());
		closeMarkers = new CustomItemizedOverlay(getApplicationContext(),
				getResources().getDrawable(R.drawable.blue_marker),
				new LinkedList<GeoPoint>());
		mediumMarkers = new CustomItemizedOverlay(getApplicationContext(),
				getResources().getDrawable(R.drawable.yellow_marker),
				new LinkedList<GeoPoint>());
		farMarkers = new CustomItemizedOverlay(getApplicationContext(),
				getResources().getDrawable(R.drawable.red_marker),
				new LinkedList<GeoPoint>());
		winMarkers = new CustomItemizedOverlay(getApplicationContext(),
				getResources().getDrawable(R.drawable.win_marker),
				new LinkedList<GeoPoint>());
		preferences = Util.getPreferences(getApplicationContext());
		// TODO fix
		String userName = preferences.getString("username", "Test");
		getSupportActionBar().setTitle(userName);
		// TODO
		SpinnerAdapter mSpinnerAdapter = ArrayAdapter.createFromResource(this,
				android.R.array.emailAddressTypes,
				android.R.layout.simple_dropdown_item_1line);
		OnNavigationListener mOnNavigationListener = new OnNavigationListener() {
			public boolean onNavigationItemSelected(int itemPosition,
					long itemId) {
				switch (itemPosition) {
				case 1:
					ViewUtils
							.showToastConnectionProblem(getApplicationContext());
					break;
				case 2:
					break;
				case 3:
					break;
				case 4:
					break;
				case 5:
					break;
				}
				return true;
			}
		};
		getSupportActionBar().setListNavigationCallbacks(mSpinnerAdapter,
				mOnNavigationListener);
		mapView = (MapView) findViewById(R.id.mapview);
		mapView.getOverlays().add(closeMarkers);
		mapView.getOverlays().add(mediumMarkers);
		mapView.getOverlays().add(farMarkers);
		mapView.getOverlays().add(foundMarkers);
		mapView.getOverlays().add(winMarkers);
		MapController mapController = mapView.getController();

		mapController.setZoom(5);
		mapView.displayZoomControls(true);
		mapView.setBuiltInZoomControls(true);

		// TODO
		int lat = (int) (40.437998 * 1E6);
		int lng = (int) (-3.624458 * 1E6);
		mapController.setCenter(new GeoPoint(lat, lng));
		mapView.invalidate();

	}

	@Override
	protected void onPause() {
		super.onPause();
		preferences = Util.getPreferences(this);
		Editor editor = preferences.edit();
		String serialization = "";
		for (GeoPoint g : foundMarkers.getMarkers()) {
			serialization += g.getLatitudeE6() + "," + g.getLongitudeE6() + "|";
		}
		editor.putString("markers", serialization);
		editor.commit();
	}

	@Override
	protected void onResume() {
		super.onResume();
		String markers = preferences.getString("markers", "");
		if (markers.length() > 0) {
			String[] elements = markers.split("|");
			for (int i = 0; i < elements.length; i++) {
				String parts[] = elements[i].split(",");
				int lat = Integer.valueOf(parts[0]);
				int lon = Integer.valueOf(parts[1]);
				foundMarkers.addItem(new GeoPoint(lat, lon));
			}
		}
	}

	@Override
	protected boolean isRouteDisplayed() {
		return false;
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		MenuInflater inflater = getSupportMenuInflater();
		inflater.inflate(R.menu.map_actionbar_menu, menu);
		return true;
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		if (item.getItemId() == R.id.ask_clue) {
			new AsyncNewClueFetcher().execute((Void) null);
		}
		// TODO show

		if (item.getItemId() == R.id.show_game_scores) {
			ViewUtils.showToastConnectionProblem(getApplicationContext());
		}

		if (item.getItemId() == R.id.clues) {
			new AsyncAllCluesFetcher().execute((Void) null);
		}
		return true;
	}

	private class AsyncNewClueFetcher extends AsyncTask<Void, Void, String> {

		@Override
		protected String doInBackground(Void... params) {
			try {
				return ServerAPI.getNextClue(getApplicationContext());
			} catch (IOException e) {
				return "FAIL";
			}
		}

		@Override
		protected void onPostExecute(String result) {
			super.onPostExecute(result);
			showStatusDialog(result);

		}

	}

	private class AsyncGameStatusRetriever extends
			AsyncTask<Void, Void, Boolean> {

		@Override
		protected Boolean doInBackground(Void... params) {
			try {
				gameStatus = ServerAPI.getGameStatus(getApplicationContext());
				Log.d("gamestatus", "true");
				return true;
			} catch (IOException e) {
				Log.d("gamestatus", "false");
				return false;
			}
		}

		@Override
		protected void onPostExecute(Boolean result) {
			super.onPostExecute(result);
			if (result) {
				GameUserData me = new GameUserData(Util.getPreferences(
						getApplicationContext()).getString("username", ""), 0,
						0);
				for (GameUserData user : gameStatus.getUsers()) {
					if (user.equals(me)) {
						me = user;
						break;
					}
				}

			} else {
				ViewUtils.showToastConnectionProblem(getApplicationContext());
			}
		}

	}

	private class AsyncAllCluesFetcher extends AsyncTask<Void, Void, Boolean> {

		@Override
		protected Boolean doInBackground(Void... params) {
			try {
				clues = ServerAPI.getCurrentClues(getApplicationContext());
				return true;
			} catch (IOException e) {
			}
			return false;
		}

		@Override
		protected void onPostExecute(Boolean result) {
			super.onPostExecute(result);
			if (result) {
				showCluesDialog();
			} else {
				ViewUtils.showToastConnectionProblem(getApplicationContext());
			}
			// TODO show dialog
		}

	}

	private void showCluesDialog() {
		// FIXME white on scroll
		Dialog dlg = new Dialog(this);
		dlg.setTitle(R.string.clues);
		LayoutInflater li = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
		View v = li.inflate(R.layout.game_hints_dialog, null, false);
		ListView lv = (ListView) v.findViewById(R.id.hints_list);
		lv.setAdapter(new ArrayAdapter<String>(getApplicationContext(),
				android.R.layout.simple_list_item_1, clues));
		dlg.setContentView(v);
		dlg.show();
	}

	private class AsyncSubmitter extends
			AsyncTask<GeoPoint, Void, Pair<SubmittedLocationResponse, String>> {
		private GeoPoint point;

		@Override
		protected Pair<SubmittedLocationResponse, String> doInBackground(
				GeoPoint... params) {
			try {
				point = params[0];
				return ServerAPI.submitLocation(getApplicationContext(), point);
			} catch (IOException e) {
				return null;
			}
		}

		@Override
		protected void onPostExecute(
				Pair<SubmittedLocationResponse, String> result) {
			super.onPostExecute(result);
			if (result != null) {
				if (result.first == SubmittedLocationResponse.FOUND) {
					foundMarkers.addItem(point);
					closeMarkers.removeItems();
					mediumMarkers.removeItems();
					farMarkers.removeItems();
					String data[] = result.second.split(";");
					showCompletedStepDialog(
							getResources().getString(R.string.completed_step,
									data[0], data[1]), false);
				}
				if (result.first == SubmittedLocationResponse.CLOSE) {
					closeMarkers.addItem(point);
				}
				if (result.first == SubmittedLocationResponse.MEDIUM) {
					mediumMarkers.addItem(point);
				}
				if (result.first == SubmittedLocationResponse.FAR) {
					farMarkers.addItem(point);
				}
				if (result.first == SubmittedLocationResponse.WIN) {
					winMarkers.addItem(point);
					Editor editor = preferences.edit();
					editor.putString("markers", "");
					editor.commit();

					showCompletedStepDialog(
							getResources().getString(R.string.finished), true);

				}
				mapView.invalidate();
			}
		}
	}

	private class CustomItemizedOverlay extends ItemizedOverlay<OverlayItem> {

		private List<GeoPoint> markers;
		private Context context;
		private Drawable marker;

		public CustomItemizedOverlay(Context context, Drawable defaultMarker,
				List<GeoPoint> markers) {

			super(defaultMarker);
			this.context = context;
			this.marker = defaultMarker;
			this.markers = markers;
			setLastFocusedIndex(-1);
			populate();
		}

		public List<GeoPoint> getMarkers() {
			return markers;
		}

		private void addItem(GeoPoint overlay) {
			markers.add(overlay);
			populate();
		}

		private void removeItems() {
			markers.clear();
			populate();
		}

		@Override
		protected OverlayItem createItem(int i) {
			return new OverlayItem(markers.get(i), "", "");
		}

		@Override
		public int size() {
			return markers.size();
		}

		@Override
		public void draw(Canvas canvas, MapView mapView, boolean shadow) {
			mapView.invalidate();
			super.draw(canvas, mapView, shadow);
			boundCenterBottom(marker);
		}

		@Override
		protected boolean onTap(int index) {
			// TODO
			return true;
		}
	}

	@Override
	public void onLocationChanged(Location location) {
		Log.i("DEBUG", "Location changed!");
		double lat = location.getLatitude();
		double lng = location.getLongitude();
		GeoPoint p = new GeoPoint(Double.valueOf(lat * 1E6).intValue(), Double
				.valueOf(lng * 1E6).intValue());
		new AsyncSubmitter().execute(p);
	}

	@Override
	public void onProviderDisabled(String provider) {
	}

	@Override
	public void onProviderEnabled(String provider) {
	}

	@Override
	public void onStatusChanged(String provider, int status, Bundle extras) {
	}

	private void showStatusDialog(String clue) {
		AlertDialog.Builder builder = new Builder(this);
		TextView tv = new TextView(getApplicationContext());
		tv.setText(clue);
		tv.setPadding(20, 20, 20, 20);
		builder.setView(tv);
		builder.setTitle(R.string.last_clue);
		builder.setPositiveButton(android.R.string.ok, new OnClickListener() {

			@Override
			public void onClick(DialogInterface dialog, int which) {
				// TODO Auto-generated method stub

			}
		});
		builder.show();
	}

	public void showCompletedStepDialog(String message, boolean finalStep) {
		// TODO dismiss other dialogs
		Builder builder = new Builder(this);
		builder.setTitle(R.string.completed_step_title);
		builder.setMessage(message);
		OnClickListener listener;
		if (!finalStep) {

			listener = new OnClickListener() {
				@Override
				public void onClick(DialogInterface dialog, int which) {
					ViewUtils.showToast(context, R.string.good_luck);
				}
			};
		} else {
			listener = new OnClickListener() {
				@Override
				public void onClick(DialogInterface dialog, int which) {
					// TODO
					// finish();
				}
			};
			builder.setNegativeButton(R.string.share_header,
					new OnClickListener() {

						@Override
						public void onClick(DialogInterface dialog, int which) {

							Intent shareIntent = new Intent(Intent.ACTION_SEND);
							shareIntent.setType("text/plain");
							shareIntent.putExtra(Intent.EXTRA_SUBJECT,
									R.string.share_message);
							startActivity(Intent.createChooser(shareIntent,
									getString(R.string.share_header)));
						}
					});

		}
		builder.setPositiveButton(android.R.string.ok, listener);
		if (currentDialog != null) {
			currentDialog.dismiss();
		}
		currentDialog = builder.create();
		currentDialog.show();
	}

}
